/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.muni.fi.pb138.videodesgapps.gui;

import com.google.api.services.drive.model.File;
import com.google.api.services.drive.model.ParentReference;
import cz.muni.fi.pb138.videodesgapps.dommanager.DomManagerImpl;
import cz.muni.fi.pb138.videodesgapps.dommanager.MediaType;
import cz.muni.fi.pb138.videodesgapps.google.GoogleConnection;
import cz.muni.fi.pb138.videodesgapps.google.GoogleDriveService;
import cz.muni.fi.pb138.videodesgapps.gui.components.MyTableCellRenderer;
import cz.muni.fi.pb138.videodesgapps.gui.components.OdfTableModel;
import java.awt.Color;
import java.awt.Desktop;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.DefaultListModel;
import javax.swing.JOptionPane;
import javax.swing.SwingWorker;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.table.DefaultTableCellRenderer;

/**
 *
 * @author xnevrela
 */
public class MainView extends javax.swing.JFrame {

    private GoogleConnection gc;
    private GoogleDriveService service;
    private DomManagerImpl manager;
    private File actualFile = new File();
    private boolean saved = true;

    /**
     * Creates new form MainView
     */
    public MainView() {
        initComponents();

        // Listen for changes in the text
        searchTF.getDocument().addDocumentListener(new DocumentListener() {
            // text was changed
            public void changedUpdate(DocumentEvent e) {
                searchText();
            }

            // text was deleted
            public void removeUpdate(DocumentEvent e) {
                searchText();
            }

            // text was inserted
            public void insertUpdate(DocumentEvent e) {
                searchText();
            }
        });
    }

    public void searchText() {
        if (!searchTF.getText().equals("")) {
            List idNumbers = manager.searchRecord(searchTF.getText(),
                    categoriesList.getSelectedValue().toString());
            MyTableCellRenderer renderer = new MyTableCellRenderer();
            renderer.setRows(idNumbers);
            recordsTable.setDefaultRenderer(Object.class, renderer);

            if (idNumbers.size() == 1) {
                searchLabel.setText("1 result found.");
            } else {
                searchLabel.setText(idNumbers.size() + " results found.");
            }

        } else {
            searchLabel.setText("");
            recordsTable.setDefaultRenderer(Object.class, new DefaultTableCellRenderer());
        }

        OdfTableModel model = (OdfTableModel) recordsTable.getModel();
        model.fireUpdateAll();

    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        connectedPanel = new javax.swing.JPanel();
        disconnectButton = new javax.swing.JButton();
        openFileButton = new javax.swing.JButton();
        statusBar = new javax.swing.JPanel();
        progressBar = new javax.swing.JProgressBar();
        statusLabel = new javax.swing.JLabel();
        quickMenuBar = new javax.swing.JPanel();
        jPanel1 = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        connectionStateLabel = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        disconnectedPanel = new javax.swing.JPanel();
        connectButton = new javax.swing.JButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        jPanel2 = new javax.swing.JPanel();
        jLabel2 = new javax.swing.JLabel();
        jScrollPane3 = new javax.swing.JScrollPane();
        categoriesList = new javax.swing.JList();
        deleteCategoryButton = new javax.swing.JButton();
        addCategoryButton = new javax.swing.JButton();
        jScrollPane2 = new javax.swing.JScrollPane();
        jPanel3 = new javax.swing.JPanel();
        jLabel4 = new javax.swing.JLabel();
        searchTF = new javax.swing.JTextField();
        jScrollPane4 = new javax.swing.JScrollPane();
        recordsTable = new javax.swing.JTable();
        deleteRecordButton = new javax.swing.JButton();
        editRecordButton = new javax.swing.JButton();
        addRecordButton = new javax.swing.JButton();
        searchLabel = new javax.swing.JLabel();
        menuBar = new javax.swing.JMenuBar();
        jMenu1 = new javax.swing.JMenu();
        connectMenuItem = new javax.swing.JMenuItem();
        jSeparator1 = new javax.swing.JPopupMenu.Separator();
        openFileMenuItem = new javax.swing.JMenuItem();
        saveFileMenuItem = new javax.swing.JMenuItem();
        saveFileAsMenuItem = new javax.swing.JMenuItem();
        jSeparator2 = new javax.swing.JPopupMenu.Separator();
        disconnectMenuItem = new javax.swing.JMenuItem();
        exitMenuItem = new javax.swing.JMenuItem();
        jMenu2 = new javax.swing.JMenu();

        connectedPanel.setBackground(new java.awt.Color(255, 255, 255));

        disconnectButton.setText("Odpojit");
        disconnectButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                disconnectButtonActionPerformed(evt);
            }
        });

        openFileButton.setText("Otevřít");
        openFileButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                openFileButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout connectedPanelLayout = new javax.swing.GroupLayout(connectedPanel);
        connectedPanel.setLayout(connectedPanelLayout);
        connectedPanelLayout.setHorizontalGroup(
            connectedPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, connectedPanelLayout.createSequentialGroup()
                .addComponent(openFileButton)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(disconnectButton, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE))
        );
        connectedPanelLayout.setVerticalGroup(
            connectedPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(connectedPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                .addComponent(disconnectButton)
                .addComponent(openFileButton))
        );

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("VideoDesGApps");
        setAutoRequestFocus(false);

        statusBar.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        javax.swing.GroupLayout statusBarLayout = new javax.swing.GroupLayout(statusBar);
        statusBar.setLayout(statusBarLayout);
        statusBarLayout.setHorizontalGroup(
            statusBarLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, statusBarLayout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(statusLabel)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );
        statusBarLayout.setVerticalGroup(
            statusBarLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(progressBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addGroup(statusBarLayout.createSequentialGroup()
                .addGap(0, 0, Short.MAX_VALUE)
                .addComponent(statusLabel))
        );

        quickMenuBar.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED));

        javax.swing.GroupLayout quickMenuBarLayout = new javax.swing.GroupLayout(quickMenuBar);
        quickMenuBar.setLayout(quickMenuBarLayout);
        quickMenuBarLayout.setHorizontalGroup(
            quickMenuBarLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 0, Short.MAX_VALUE)
        );
        quickMenuBarLayout.setVerticalGroup(
            quickMenuBarLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 23, Short.MAX_VALUE)
        );

        jPanel1.setBackground(new java.awt.Color(255, 255, 255));
        jPanel1.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        jPanel1.setLayout(new java.awt.GridBagLayout());

        jLabel1.setIcon(new javax.swing.ImageIcon(getImage("Google_Logo.png")));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        jPanel1.add(jLabel1, gridBagConstraints);

        connectionStateLabel.setForeground(java.awt.Color.RED);
        connectionStateLabel.setText("<html><b>Nejste připojeni</b></html>");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.insets = new java.awt.Insets(5, 0, 0, 0);
        jPanel1.add(connectionStateLabel, gridBagConstraints);

        jLabel3.setText("ke svému účtu Google");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 0);
        jPanel1.add(jLabel3, gridBagConstraints);

        disconnectedPanel.setBackground(new java.awt.Color(255, 255, 255));
        disconnectedPanel.setLayout(new java.awt.GridBagLayout());

        connectButton.setText("Připojit");
        connectButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                connectButtonActionPerformed(evt);
            }
        });
        disconnectedPanel.add(connectButton, new java.awt.GridBagConstraints());

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        jPanel1.add(disconnectedPanel, gridBagConstraints);

        jLabel2.setText("Kategorie:");

        categoriesList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        categoriesList.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
            public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
                categoriesListValueChanged(evt);
            }
        });
        jScrollPane3.setViewportView(categoriesList);

        deleteCategoryButton.setText("Smazat");
        deleteCategoryButton.setEnabled(false);
        deleteCategoryButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                deleteCategoryButtonActionPerformed(evt);
            }
        });

        addCategoryButton.setText("Přidat");
        addCategoryButton.setEnabled(false);
        addCategoryButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addCategoryButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup()
                        .addGap(0, 0, Short.MAX_VALUE)
                        .addComponent(addCategoryButton)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(deleteCategoryButton))
                    .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 181, Short.MAX_VALUE)
                    .addComponent(jLabel2))
                .addContainerGap())
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabel2)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 191, Short.MAX_VALUE)
                .addGap(18, 18, 18)
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(deleteCategoryButton)
                    .addComponent(addCategoryButton))
                .addContainerGap())
        );

        jScrollPane1.setViewportView(jPanel2);

        jLabel4.setText("Hledání:");

        searchTF.setEnabled(false);
        searchTF.setName(""); // NOI18N

        recordsTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        recordsTable.getSelectionModel().addListSelectionListener(new javax.swing.event.ListSelectionListener() {
            public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
                recordsTableValueChanged(evt);
            }
        });
        jScrollPane4.setViewportView(recordsTable);

        deleteRecordButton.setText("Smazat");
        deleteRecordButton.setEnabled(false);
        deleteRecordButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                deleteRecordButtonActionPerformed(evt);
            }
        });

        editRecordButton.setText("Změnit");
        editRecordButton.setEnabled(false);
        editRecordButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                editRecordButtonActionPerformed(evt);
            }
        });

        addRecordButton.setText("Přidat");
        addRecordButton.setEnabled(false);
        addRecordButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addRecordButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane4, javax.swing.GroupLayout.DEFAULT_SIZE, 472, Short.MAX_VALUE)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup()
                        .addGap(0, 0, Short.MAX_VALUE)
                        .addComponent(addRecordButton)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(editRecordButton)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(deleteRecordButton))
                    .addGroup(jPanel3Layout.createSequentialGroup()
                        .addComponent(jLabel4)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(searchTF, javax.swing.GroupLayout.PREFERRED_SIZE, 254, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(18, 18, 18)
                        .addComponent(searchLabel)
                        .addGap(0, 0, Short.MAX_VALUE)))
                .addContainerGap())
        );
        jPanel3Layout.setVerticalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel4)
                    .addComponent(searchTF, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(searchLabel))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane4, javax.swing.GroupLayout.DEFAULT_SIZE, 343, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(deleteRecordButton)
                    .addComponent(editRecordButton)
                    .addComponent(addRecordButton))
                .addContainerGap())
        );

        searchLabel.getAccessibleContext().setAccessibleName("resultsLabel");

        jScrollPane2.setViewportView(jPanel3);

        jMenu1.setText("Soubor");

        connectMenuItem.setText("Připojit ke Google Drive ...");
        connectMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                connectButtonActionPerformed(evt);
            }
        });
        jMenu1.add(connectMenuItem);
        jMenu1.add(jSeparator1);

        openFileMenuItem.setText("Otevřít soubor ...");
        openFileMenuItem.setEnabled(false);
        openFileMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                openFileButtonActionPerformed(evt);
            }
        });
        jMenu1.add(openFileMenuItem);

        saveFileMenuItem.setText("Uložit soubor");
        saveFileMenuItem.setEnabled(false);
        saveFileMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveFileButtonActionPerformed(evt);
            }
        });
        jMenu1.add(saveFileMenuItem);

        saveFileAsMenuItem.setText("Uložit soubor jako ...");
        saveFileAsMenuItem.setEnabled(false);
        saveFileAsMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveAsFileButtonActionPerformed(evt);
            }
        });
        jMenu1.add(saveFileAsMenuItem);
        jMenu1.add(jSeparator2);

        disconnectMenuItem.setText("Odpojit od Google Drive");
        disconnectMenuItem.setEnabled(false);
        disconnectMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                disconnectButtonActionPerformed(evt);
            }
        });
        jMenu1.add(disconnectMenuItem);

        exitMenuItem.setText("Konec");
        exitMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                exitMenuItemActionPerformed(evt);
            }
        });
        jMenu1.add(exitMenuItem);

        menuBar.add(jMenu1);

        jMenu2.setText("Edit");
        menuBar.add(jMenu2);

        setJMenuBar(menuBar);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(statusBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jScrollPane1))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 484, Short.MAX_VALUE))
            .addComponent(quickMenuBar, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addComponent(quickMenuBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 145, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jScrollPane1))
                    .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(statusBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void connectButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_connectButtonActionPerformed
        if (gc == null) {
            gc = new GoogleConnection();
        }
        GoogleConnectionDialog gcd = new GoogleConnectionDialog(this, true);
        gcd.setLocationRelativeTo(this);
        gcd.setConnectionUrl(gc.getAuthentizationUrl());

        if (Desktop.isDesktopSupported()) {
            try {
                Desktop.getDesktop().browse(new URI(gc.getAuthentizationUrl()));
            } catch (IOException ex) {
                Logger.getLogger(MainView.class.getName()).log(Level.SEVERE, null, ex);
            } catch (URISyntaxException ex) {
                Logger.getLogger(MainView.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

        int result = gcd.showDialog();

        if (result == GoogleConnectionDialog.RESULT_OK) {
            SwingWorker task = new ConnectToGoogleDriveTask(gc, gcd.getCode());
            task.addPropertyChangeListener(
                    new PropertyChangeListener() {
                        public void propertyChange(PropertyChangeEvent evt) {
                            if ("state".equals(evt.getPropertyName())) {
                                Object value = evt.getNewValue();
                                if (value.equals(SwingWorker.StateValue.STARTED)) {
                                    statusLabel.setText("Připojování k autentizační službě Google");
                                    progressBar.setValue(20);
                                }
                                if (value.equals(SwingWorker.StateValue.DONE)) {
                                    statusLabel.setText("Připojování ukončeno");
                                    progressBar.setValue(0);
                                }
                            }
                        }
                    });

            task.execute();
        }
    }//GEN-LAST:event_connectButtonActionPerformed

    private void disconnectButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_disconnectButtonActionPerformed
        if (!saved) {
            int dialogResult = JOptionPane.showConfirmDialog(this, "Opravdu se chcete odpojit od svého účtu Google? "
                    + "Veškerá neuložená data budou ztracena", "Potvrzení", JOptionPane.YES_NO_OPTION);

            if (dialogResult == JOptionPane.YES_OPTION) {
                disconnect();
            }
        } else {
            disconnect();
        }
    }//GEN-LAST:event_disconnectButtonActionPerformed

    private void disconnect() {
        gc.close();
        gc = null;

        categoriesList.clearSelection();
        categoriesList.setListData(new Object[]{});

        connectionStateLabel.setText("<html><b>Nejste připojeni</b></html>");
        connectionStateLabel.setForeground(Color.RED);

        java.awt.GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        jPanel1.remove(connectedPanel);
        jPanel1.add(disconnectedPanel, gridBagConstraints);
        jPanel1.repaint();

        // Enabling menu items
        connectMenuItem.setEnabled(true);
        openFileMenuItem.setEnabled(false);
        saveFileMenuItem.setEnabled(false);
        saveFileAsMenuItem.setEnabled(false);
        disconnectMenuItem.setEnabled(false);

        addCategoryButton.setEnabled(false);

        statusLabel.setText("Odpojeno");

        saved = true;
    }

    private void openFileButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openFileButtonActionPerformed
        if (!saved) {
            int dialogResult = JOptionPane.showConfirmDialog(this, "Opravdu se otevřít nový soubor? "
                    + "Veškerá neuložená data budou ztracena", "Potvrzení", JOptionPane.YES_NO_OPTION);
            if (dialogResult == JOptionPane.YES_OPTION) {
                openFile();
            }
        } else {
            openFile();
        }


    }//GEN-LAST:event_openFileButtonActionPerformed
    private void openFile() {
        GoogleFileChooserDialog fileChooser = new GoogleFileChooserDialog(this, true, service);
        fileChooser.setLocationRelativeTo(this);
        int result = fileChooser.showOpenDialog();

        if (result == GoogleFileChooserDialog.RESULT_OK) {
            File file = fileChooser.getSelectedFile();

            DownloadFileTask task = new DownloadFileTask(service, file);
            task.addPropertyChangeListener(
                    new PropertyChangeListener() {
                        public void propertyChange(PropertyChangeEvent evt) {
                            if ("state".equals(evt.getPropertyName())) {
                                Object value = evt.getNewValue();
                                if (value.equals(SwingWorker.StateValue.STARTED)) {
                                    statusLabel.setText("Stahování souboru");
                                    progressBar.setValue(20);
                                }
                                if (value.equals(SwingWorker.StateValue.DONE)) {
                                    statusLabel.setText("Soubor otevřen");
                                    progressBar.setValue(0);
                                }
                            }
                        }
                    });

            task.execute();

            for (ActionListener listener : openFileButton.getActionListeners()) {
                openFileButton.removeActionListener(listener);
            }

            openFileButton.setText("Uložit");
            openFileButton.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    saveFileButtonActionPerformed(e);
                }
            });
        }
    }

    private void recordsTableValueChanged(javax.swing.event.ListSelectionEvent evt) {
        boolean selected = recordsTable.getSelectedRow() != -1;

        editRecordButton.setEnabled(selected);
        deleteRecordButton.setEnabled(selected);
    }

    private void categoriesListValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_categoriesListValueChanged
        boolean selected = !categoriesList.isSelectionEmpty();

        deleteCategoryButton.setEnabled(selected);

        searchTF.setEnabled(selected);
        addRecordButton.setEnabled(selected);
        editRecordButton.setEnabled(editRecordButton.isEnabled() && selected);
        deleteRecordButton.setEnabled(deleteRecordButton.isEnabled() && selected);

        if (selected) {
            OdfTableModel tableModel = new OdfTableModel();

            MediaType mediaType = manager.loadTableToMediaType(categoriesList.getSelectedValue().toString());
            tableModel.setMediaType(mediaType);
            recordsTable.setModel(tableModel);
        } else {
            recordsTable.setModel(new OdfTableModel());
        }

        this.searchText();

    }//GEN-LAST:event_categoriesListValueChanged

    private void addCategoryButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addCategoryButtonActionPerformed
        MediaType type = Dialogs.newMediaTypeDialog(manager.getMediaNames());

        if (type != null) {
            manager.addMediaType(type.getName(), type.getAttributes());
            DefaultListModel model = (DefaultListModel) categoriesList.getModel();

            model.addElement(type.getName());
            saved = false;
        }
    }//GEN-LAST:event_addCategoryButtonActionPerformed

    private void deleteCategoryButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteCategoryButtonActionPerformed
        manager.deleteMediaType(categoriesList.getSelectedValue().toString());
        DefaultListModel model = (DefaultListModel) categoriesList.getModel();
        int index = categoriesList.getSelectedIndex();
        model.remove(index);

        saved = false;
    }//GEN-LAST:event_deleteCategoryButtonActionPerformed

    private void addRecordButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addRecordButtonActionPerformed
        OdfTableModel model = (OdfTableModel) recordsTable.getModel();
        List record = Dialogs.newRecordDialog(model.getMediaType());

        if (record != null) {
            model.fireInserted();
            manager.addRecord(categoriesList.getSelectedValue().toString(), record);
        }

        saved = false;
    }//GEN-LAST:event_addRecordButtonActionPerformed

    private void saveFileButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveFileButtonActionPerformed
        if (this.actualFile.getId().isEmpty()) {
            // File is new, is not loaded
            saveAsFileButtonActionPerformed(evt);
        } else {
            SwingWorker task;

            // Content
            java.io.File content = manager.saveSpreadSheet();

            task = new SaveFileTask(service, actualFile, content);

            task.addPropertyChangeListener(
                    new PropertyChangeListener() {
                        public void propertyChange(PropertyChangeEvent evt) {
                            if ("state".equals(evt.getPropertyName())) {
                                Object value = evt.getNewValue();
                                if (value.equals(SwingWorker.StateValue.STARTED)) {
                                    statusLabel.setText("Ukládání souboru");
                                    progressBar.setValue(20);
                                }
                                if (value.equals(SwingWorker.StateValue.DONE)) {
                                    statusLabel.setText("Soubor uložen");
                                    progressBar.setValue(0);
                                }
                            }
                        }
                    });

            task.execute();
        }
    }//GEN-LAST:event_saveFileButtonActionPerformed

    private void saveAsFileButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveAsFileButtonActionPerformed
        GoogleFileChooserDialog fileChooser = new GoogleFileChooserDialog(this, true, service);
        fileChooser.setLocationRelativeTo(this);
        int result = fileChooser.showSaveDialog();

        SwingWorker task;
        if (result == GoogleFileChooserDialog.RESULT_OK) {
            File file = fileChooser.getSelectedFile();

            if (service.isFolder(file)) {
                // Folder selected. Need to get name of the new file from the text field
                String name = fileChooser.getInsertedFileName();
                if (!name.endsWith(".ods")) {
                    name += ".ods";
                }

                File newFile = new File();
                newFile.setTitle(name);
                newFile.setDescription(actualFile.getDescription());
                newFile.setMimeType(actualFile.getMimeType());
                ParentReference parent = new ParentReference();
                parent.setId(file.getId());
                newFile.setParents(Collections.singletonList(parent));

                // Content
                java.io.File content = manager.saveSpreadSheet();

                task = new SaveNewFileTask(service, newFile, content);
            } else {
                // Content
                java.io.File content = manager.saveSpreadSheet();

                task = new SaveFileTask(service, file, content);
            }
            task.addPropertyChangeListener(
                    new PropertyChangeListener() {
                        public void propertyChange(PropertyChangeEvent evt) {
                            if ("state".equals(evt.getPropertyName())) {
                                Object value = evt.getNewValue();
                                if (value.equals(SwingWorker.StateValue.STARTED)) {
                                    statusLabel.setText("Ukládání souboru");
                                    progressBar.setValue(20);
                                }
                                if (value.equals(SwingWorker.StateValue.DONE)) {
                                    statusLabel.setText("Soubor uložen");
                                    progressBar.setValue(0);
                                }
                            }
                        }
                    });

            task.execute();
        }
    }//GEN-LAST:event_saveAsFileButtonActionPerformed

    private void deleteRecordButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteRecordButtonActionPerformed
        OdfTableModel model = (OdfTableModel) recordsTable.getModel();
        manager.deleteRecord(categoriesList.getSelectedValue().toString(), recordsTable.getSelectedRow() + 1);
        model.getMediaType().getRecords().remove(recordsTable.getSelectedRow());

        model.fireDeleted(recordsTable.getSelectedRow());

        saved = false;
    }//GEN-LAST:event_deleteRecordButtonActionPerformed

    private void editRecordButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editRecordButtonActionPerformed
        OdfTableModel model = (OdfTableModel) recordsTable.getModel();
        List newAttributes = Dialogs.editRecordDialog(recordsTable.getSelectedRow(), model.getMediaType());
        manager.editRecord(categoriesList.getSelectedValue().toString(), recordsTable.getSelectedRow() + 1, newAttributes);

        model.fireUpdate(recordsTable.getSelectedRow());

        if (newAttributes != null) {
            manager.editRecord(categoriesList.getSelectedValue().toString(), recordsTable.getSelectedRow() + 1, newAttributes);
            model.fireUpdate(recordsTable.getSelectedRow());
        }
        saved = false;
    }//GEN-LAST:event_editRecordButtonActionPerformed

    private void exitMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exitMenuItemActionPerformed
        if (!saved) {
            int dialogResult = JOptionPane.showConfirmDialog(this, "Opravdu chcete ukon4it aplikaci VideoDesGApps? "
                    + "Veškerá neuložená data budou ztracena", "Potvrzení", JOptionPane.YES_NO_OPTION);

            if (dialogResult == JOptionPane.YES_OPTION) {
                System.exit(0);
            }
        } else {
            disconnect();
        }
    }//GEN-LAST:event_exitMenuItemActionPerformed
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton addCategoryButton;
    private javax.swing.JButton addRecordButton;
    private javax.swing.JList categoriesList;
    private javax.swing.JButton connectButton;
    private javax.swing.JMenuItem connectMenuItem;
    private javax.swing.JPanel connectedPanel;
    private javax.swing.JLabel connectionStateLabel;
    private javax.swing.JButton deleteCategoryButton;
    private javax.swing.JButton deleteRecordButton;
    private javax.swing.JButton disconnectButton;
    private javax.swing.JMenuItem disconnectMenuItem;
    private javax.swing.JPanel disconnectedPanel;
    private javax.swing.JButton editRecordButton;
    private javax.swing.JMenuItem exitMenuItem;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenu jMenu2;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JScrollPane jScrollPane4;
    private javax.swing.JPopupMenu.Separator jSeparator1;
    private javax.swing.JPopupMenu.Separator jSeparator2;
    private javax.swing.JMenuBar menuBar;
    private javax.swing.JButton openFileButton;
    private javax.swing.JMenuItem openFileMenuItem;
    private javax.swing.JProgressBar progressBar;
    private javax.swing.JPanel quickMenuBar;
    private javax.swing.JTable recordsTable;
    private javax.swing.JMenuItem saveFileAsMenuItem;
    private javax.swing.JMenuItem saveFileMenuItem;
    private javax.swing.JLabel searchLabel;
    private javax.swing.JTextField searchTF;
    private javax.swing.JPanel statusBar;
    private javax.swing.JLabel statusLabel;
    // End of variables declaration//GEN-END:variables

    /**
     * SwingWorker background task downloading file from Google Drive
     *
     */
    private class DownloadFileTask extends SwingWorker<java.io.File, Integer> {

        private File fileToDownload;
        private GoogleDriveService service;

        public DownloadFileTask(GoogleDriveService service, File file) {
            this.service = service;
            this.fileToDownload = file;
        }

        @Override
        protected java.io.File doInBackground() throws Exception {
            return service.downloadFile(fileToDownload);
        }

        @Override
        protected void done() {
            statusLabel.setText("Soubor stáhnut");
            try {
                java.io.File downloadedFile = this.get();

                actualFile = fileToDownload;

                manager = new DomManagerImpl(downloadedFile);

                DefaultListModel model = new DefaultListModel();
                for (int i = 0; i < manager.getMediaNames().size(); i++) {
                    model.add(i, manager.getMediaNames().get(i));
                }
                categoriesList.setModel(model);

                saved = true;
                addCategoryButton.setEnabled(true);
            } catch (InterruptedException ex) {
                Logger.getLogger(MainView.class.getName()).log(Level.SEVERE, null, ex);
            } catch (ExecutionException ex) {
                Logger.getLogger(MainView.class.getName()).log(Level.SEVERE, null, ex);
                JOptionPane.showMessageDialog(rootPane, "Chyba při otevírání souboru", "Chyba", JOptionPane.ERROR_MESSAGE);
            }
        }
    }

    /**
     * SwingWorker background task saving updating file saved at Google Drive
     */
    private class SaveFileTask extends SwingWorker<File, Integer> {

        private File fileToSave;
        private java.io.File content;
        private GoogleDriveService service;

        public SaveFileTask(GoogleDriveService service, File file, java.io.File content) {
            this.service = service;
            this.fileToSave = file;
            this.content = content;
        }

        @Override
        protected File doInBackground() throws Exception {
            return service.updateFile(fileToSave, content);
        }

        @Override
        protected void done() {
            try {
                File updatedFile = this.get();

                if (updatedFile == null) {
                    JOptionPane.showMessageDialog(rootPane, "Chyba při ukládání souboru", "Chyba", JOptionPane.ERROR_MESSAGE);
                } else {
                    actualFile = updatedFile;
                    statusLabel.setText("Soubor uložen");
                    saved = true;
                }
            } catch (InterruptedException ex) {
                Logger.getLogger(MainView.class.getName()).log(Level.SEVERE, null, ex);
                JOptionPane.showMessageDialog(rootPane, "Chyba při ukládání souboru", "Chyba", JOptionPane.ERROR_MESSAGE);
            } catch (ExecutionException ex) {
                Logger.getLogger(MainView.class.getName()).log(Level.SEVERE, null, ex);
                JOptionPane.showMessageDialog(rootPane, "Chyba při ukládání souboru", "Chyba", JOptionPane.ERROR_MESSAGE);
            }
        }
    }

    /**
     * SwingWorker background task saving new file to Google Drive
     */
    private class SaveNewFileTask extends SwingWorker<File, Integer> {

        private File fileToSave;
        private java.io.File content;
        private GoogleDriveService service;

        public SaveNewFileTask(GoogleDriveService service, File file, java.io.File content) {
            this.service = service;
            this.fileToSave = file;
            this.content = content;
        }

        @Override
        protected File doInBackground() throws Exception {
            return service.saveFile(fileToSave, content);
        }

        @Override
        protected void done() {
            try {
                File updatedFile = this.get();

                if (updatedFile == null) {
                    JOptionPane.showMessageDialog(rootPane, "Chyba při ukládání souboru", "Chyba", JOptionPane.ERROR_MESSAGE);
                } else {
                    actualFile = updatedFile;
                    statusLabel.setText("Soubor uložen");

                    saved = true;
                }
            } catch (InterruptedException ex) {
                Logger.getLogger(MainView.class.getName()).log(Level.SEVERE, null, ex);
                JOptionPane.showMessageDialog(rootPane, "Chyba při ukládání souboru", "Chyba", JOptionPane.ERROR_MESSAGE);
            } catch (ExecutionException ex) {
                Logger.getLogger(MainView.class.getName()).log(Level.SEVERE, null, ex);
                JOptionPane.showMessageDialog(rootPane, "Chyba při ukládání souboru", "Chyba", JOptionPane.ERROR_MESSAGE);
            }
        }
    }

    /**
     * SwingWorker background task connecting to Google Drive account.
     */
    private class ConnectToGoogleDriveTask extends SwingWorker<GoogleDriveService, Integer> {

        public static final int CONNECTION_SUCCESSFUL = 0;
        public static final int CONNECTION_FAILED = 1;
        private GoogleConnection gc;
        private String code;

        public ConnectToGoogleDriveTask(GoogleConnection gc, String code) {
            this.gc = gc;
            this.code = code;
        }

        @Override
        protected GoogleDriveService doInBackground() throws Exception {
            GoogleDriveService gds = null;
            try {
                gc.connect(code);
                if (gc.isConnected()) {
                    publish(CONNECTION_SUCCESSFUL);
                    gds = gc.buildService();
                } else {
                    publish(CONNECTION_FAILED);
                }

            } catch (Exception ex) {
                Logger.getLogger(MainView.class
                        .getName()).log(Level.INFO, null, ex);
            }
            return gds;
        }

        @Override
        protected void process(List<Integer> chunks) {
            for (int chunk : chunks) {
                if (chunk == CONNECTION_SUCCESSFUL) {
                    statusLabel.setText("Připojeno. Ověřuji oprávnění");
                    progressBar.setValue(50);
                } else {
                    statusLabel.setText("Chyba připojování");
                    progressBar.setValue(0);
                }
            }
        }

        @Override
        protected void done() {
            try {
                GoogleDriveService gds = this.get();

                if (gds != null) {
                    service = gds;

                    connectionStateLabel.setText("<html><b>Jste připojeni</b></html>");
                    connectionStateLabel.setForeground(Color.GREEN);

                    for (ActionListener listener : openFileButton.getActionListeners()) {
                        openFileButton.removeActionListener(listener);
                    }

                    openFileButton.setText("Otevřít");
                    openFileButton.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e) {
                            openFileButtonActionPerformed(e);
                        }
                    });

                    java.awt.GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints();
                    gridBagConstraints.gridx = 0;
                    gridBagConstraints.gridy = 3;
                    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
                    jPanel1.remove(disconnectedPanel);
                    jPanel1.add(connectedPanel, gridBagConstraints);
                    jPanel1.repaint();

                    // Enabling menu items
                    connectMenuItem.setEnabled(false);
                    openFileMenuItem.setEnabled(true);
                    saveFileMenuItem.setEnabled(true);
                    saveFileAsMenuItem.setEnabled(true);
                    disconnectMenuItem.setEnabled(true);

                    addCategoryButton.setEnabled(true);

                    saved = true;
                } else {
                    JOptionPane.showMessageDialog(null, "Nepodařilo se připojit k Vašemu účtu Google", "Chyba připojení", JOptionPane.INFORMATION_MESSAGE);
                }
            } catch (InterruptedException ex) {
                Logger.getLogger(MainView.class
                        .getName()).log(Level.SEVERE, null, ex);
                JOptionPane.showMessageDialog(rootPane,
                        "Chyba při připojování ke Google Drive", "Chyba", JOptionPane.ERROR_MESSAGE);
            } catch (ExecutionException ex) {
                Logger.getLogger(MainView.class
                        .getName()).log(Level.SEVERE, null, ex);
                JOptionPane.showMessageDialog(rootPane,
                        "Chyba při připojování ke Google Drive", "Chyba", JOptionPane.ERROR_MESSAGE);
            }
        }
    }

    public static Image getImage(final String pathAndFileName) {
        final URL url = Thread.currentThread().getContextClassLoader().getResource(pathAndFileName);
        return Toolkit.getDefaultToolkit().getImage(url);
    }
}
